#include "graphe.h"

#include <string.h>

void graphe_create(Graphe** graphe)
{
    (*graphe) = (Graphe*) malloc(sizeof(Graphe));
    graphe_initialize((*graphe));
}

void graphe_initialize(Graphe* graphe)
{
    list_initialize(&graphe->noeuds,object_getNoeud(),1);
}

void graphe_clear(Graphe* graphe)
{
    if(graphe != NULL)
    {
        while(graphe->noeuds.count > 0)
            graphe_removeNode(graphe,(Noeud*)list_getFirstValue(&graphe->noeuds));
        list_clear(&graphe->noeuds);
    }
}

void graphe_destroy(Graphe** graphe)
{
    graphe_clear((*graphe));
    free((*graphe));
    (*graphe) = NULL;
}

int graphe_getNodeIndexByValue(Graphe* graphe, const char* name)
{
    int i;
    for(i = 0; i < graphe->noeuds.count; i++)
    {
        if(strcmp(((Noeud*)list_getAt(&graphe->noeuds,i)->value)->element,name) == 0)
            return i;
    }
    return -1;
}

int graphe_addNode(Graphe* graphe, const char* name)
{
    if(graphe_getNodeIndexByValue(graphe,name) == -1)
    {
        Noeud noeud;
        noeud_initialize(&noeud,name);
        list_insertLast(&graphe->noeuds,(void*)(&noeud));
        noeud_clear(&noeud);
        return 1;
    }
    else
        return 0;
}

int graphe_removeNode(Graphe* graphe, Noeud* noeud)
{
    if(noeud != NULL)
    {
        Cell* cell;
        Arc* arc;
        cell = noeud->successeurs.first;
        while (cell != NULL)
        {
            arc = (Arc*)cell->value;
            noeud_removeSuccessor(noeud,arc->successeur,arc->cost);
            cell = noeud->successeurs.first;
        }

        cell = noeud->predecesseurs.first;
        while (cell != NULL)
        {
            arc = (Arc*)cell->value;
            noeud_removePredecessor(noeud,arc->predecesseur,arc->cost);
            cell = noeud->predecesseurs.first;
        }

        list_remove(&graphe->noeuds,(void*)noeud);
        return 1;
    }
    else
        return 0;
}

int graphe_removeNodeByValue(Graphe* graphe, const char* name)
{
    int index = graphe_getNodeIndexByValue(graphe,name);
    if(index != -1)
    {
        return graphe_removeNodeByIndex(graphe,index);
    }
    else
        return 0;
}

int graphe_removeNodeByIndex(Graphe* graphe, int index)
{
    Noeud* noeud = (Noeud*)list_getValueAt(&graphe->noeuds,index);
    if(noeud != NULL)
        return graphe_removeNode(graphe,noeud);
    else
        return 0;
}

int graphe_addArcByIndex(Graphe* graphe, int index1, int index2, int cost)
{
    Noeud* noeud1 = (Noeud*)list_getValueAt(&graphe->noeuds,index1);
    Noeud* noeud2 = (Noeud*)list_getValueAt(&graphe->noeuds,index2);
    if((noeud1 != NULL) && (noeud2 != NULL))
        return noeud_addSuccessor(noeud1,noeud2,cost);
    return 0;
}

int graphe_addArcByValue(Graphe* graphe, const char* name1, const char* name2,int cost)
{
    int index1 = graphe_getNodeIndexByValue(graphe,name1);
    int index2 = graphe_getNodeIndexByValue(graphe,name2);
    if((index1 != -1) && (index2 != -1))
        return graphe_addArcByIndex(graphe,index1,index2,cost);
    return 0;
}

void graphe_print(const Graphe* graphe)
{
    int i,j;
    Noeud* noeud;
    Arc* arc;
    for(i = 0; i < graphe->noeuds.count; i++)
    {
        noeud = (Noeud*)list_getValueAt(&graphe->noeuds,i);
        printf("Ville : %s\n",noeud->element);
        for(j = 0; j < noeud->successeurs.count; j++)
        {
            arc = (Arc*)list_getValueAt(&noeud->successeurs,j);
            printf("\t Route vers la ville %s, %d kilomètres.\n",arc->successeur->element,arc->cost);
        }
        fflush(stdout);
    }
}
